/**
 * @author luruirui
 * @date 2024-01-06
 * @description 基于ScrollView的循环列表(实现了横向滚动，纵向有空再做)
 */

import { EVENT_NAME_ENUM } from "../../base/EnumIndex";
import { Tools } from "../../common/Tools";
import { EventManager } from "../../manager/EventManager";
import { LvInfo } from "../../model/OtherModel";
import PageNode from "./PageNode";

const { ccclass, property } = cc._decorator;

@ccclass
export default class ListView extends cc.Component {
    @property(cc.Node)
    private itemNode: cc.Node = null;

    /** 行数，默认一行 */
    private row: number = 1;
    /** 列数，默认一列 */
    private col: number = 1;

    private scrollView: cc.ScrollView = null;
    private view: cc.Node = null;
    private content: cc.Node = null;
    private layout: cc.Layout = null;

    private itemDataList: unknown[];
    private itemNodeList: cc.Node[] = [];
    private currentItem: cc.Node = null;

    private viewNum: number = 0;
    private createNum: number = 0;


    isScrollEnd: boolean = false;
    isScroling: boolean = false;

    private updateTimer: number = 0;
    private updateInterval: number = 0.03;
    private lastContentPosX: number = 0;
    private lastContentPosY: number = 0;

    private pageId: number = 0;

    onLoad() {
        this.scrollView = this.node.getComponent(cc.ScrollView);
        this.view = this.node.getChildByName("view");
        this.content = this.scrollView.content;
        this.layout = this.content.getComponent(cc.Layout);
    }

    start() {
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
    }

    onDestroy() {
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
    }

    initList(pageId: number, itemDataList: unknown[]) {
        this.itemDataList = [];
        this.content.removeAllChildren();
        this.itemNodeList = [];
        this.pageId = pageId;
        this.itemDataList = itemDataList;
        cc.log(this.itemDataList.length)
        this.caculateParam();
        this.createListView();
    }

    caculateParam() {
        let width = this.view.width;
        let height = this.view.height;
        let itemWidth = this.itemNode.width;
        let itemHeight = this.itemNode.height;

        let totalNum = this.itemDataList.length;

        // 横向滑动 高度固定，行数固定
        this.row = Math.floor(
            (height + this.layout.spacingY - this.layout.paddingTop - this.layout.paddingBottom)
            /
            (itemHeight + this.layout.spacingY)
        );
        this.col = Math.floor(
            (width + this.layout.spacingX - this.layout.paddingLeft - this.layout.paddingRight)
            /
            (itemWidth + this.layout.spacingX)
        );
        if (this.scrollView.horizontal) {
            this.createNum = this.row * (this.col + 1);
            this.viewNum = this.row * this.col;

            this.content.height = height;
            this.col = Math.ceil(totalNum / this.row);

            this.content.width = this.layout.paddingLeft + this.layout.paddingRight +
                this.col * itemWidth + (this.col - 1) * this.layout.spacingX
            this.content.x = (this.content.width - width) / 2;
        } else {
            this.createNum = (this.row + 1) * this.col;
            this.viewNum = this.row * this.col;

            this.content.width = width;
            this.row = Math.ceil(totalNum / this.col);

            this.content.height = this.layout.paddingTop + this.layout.paddingBottom +
                this.row * itemHeight + (this.row - 1) * this.layout.spacingY;
            this.content.y = -(this.content.height - height) / 2
        }
        // cc.log("caculateParam", this.row, this.col, this.viewNum, this.createNum);
        this.layout.enabled = false;
        // 记录初始坐标
        this.lastContentPosX = this.content.x;
        this.lastContentPosY = this.content.y;
    }

    createListView() {
        let pageNum = this.pageId - 1;
        let currentPageNum = this.pageId - 1;
        let offset = pageNum * (this.itemNode.width + this.layout.spacingX);
        this.content.x -= offset;
        //如果不是第一页，则让UI向左挪一位，解决最后一页时数组越界问题
        if (pageNum > 0) pageNum -= 1;
        for (let i = 0; i < this.createNum; i++) {
            let idx = i + pageNum;
            if (!this.itemDataList[idx]) {
                this.currentItem = this.itemNodeList[0];
                return;
            }
            let item = cc.instantiate(this.itemNode);
            item.getComponent(PageNode).init(idx, this.itemDataList[idx] as LvInfo[]);
            this.content.addChild(item);
            this.itemNodeList.push(item);
            item.x = -(this.content.width / 2 - item.width / 2) + (idx * item.width);
        }
        if (currentPageNum == 0) {
            this.currentItem = this.itemNodeList[0];
        } else {
            this.currentItem = this.itemNodeList[1];
        }
    }
    update(dt: number) {
        if (!this.scrollView.isScrolling() && !this.isScroling) return;

        this.isScrollEnd = false;
        this.updateTimer += dt;
        if (this.updateTimer < this.updateInterval) return; // we don't need to do the math every frame
        this.updateTimer = 0;
        let items = this.itemNodeList;
        if (this.scrollView.horizontal) {
            let isRight = this.content.x > this.lastContentPosX; // scrolling direction
            let offset = (this.itemNode.width + this.layout.spacingX) * items.length;
            // cc.log("--------------------------------------------------");
            for (let i = 0; i < items.length; ++i) {
                let viewPos = Tools.getToNodePosForNode(items[i], this.node)
                // cc.log(i, viewPos.x, items[i].x, offset, this.content.width)
                if (isRight) {
                    // if away from buffer zone and not reaching left of content
                    if (viewPos.x > this.view.width && items[i].x - offset > -this.content.width / 2) {
                        let page = items[i].getComponent(PageNode);
                        let idx = page.idx - items.length;
                        let data = this.itemDataList[idx] as LvInfo[]
                        if (data) {
                            this.currentItem = items[i];
                            items[i].x = items[i].x - offset;
                            page.updateView(idx, data);
                            this.updatePageLabel();
                        }
                    }
                } else {
                    // if away from buffer zone and not reaching right of content
                    if (viewPos.x < -this.view.width && items[i].x + offset < this.content.width / 2) {
                        let page = items[i].getComponent(PageNode);
                        let idx = page.idx + items.length;
                        let data = this.itemDataList[idx] as LvInfo[]
                        if (data) {
                            this.currentItem = items[i];
                            items[i].x = items[i].x + offset;
                            page.updateView(idx, data);
                            this.updatePageLabel();
                        }
                    }
                }
            }
            this.lastContentPosX = this.content.x;
        } else {
            // TODO: 纵向实现
        }
        this.isScroling = false;
    }

    scrollEvent(sender: cc.ScrollView, event: cc.ScrollView.EventType) {
        switch (event) {
            case cc.ScrollView.EventType.SCROLL_ENDED:
                if (this.isScrollEnd) return;//防止无限调用
                this.isScrollEnd = true;
                cc.log("onScrollEnd")
                this.updatePage();
                break;
            default:
                break;
        }
    }

    updatePageLabel() {
        let pageIdx = 0;
        if (this.scrollView.horizontal) {
            let x = this.currentItem.x + this.content.width / 2 - this.currentItem.width / 2;
            pageIdx = Math.floor(x / this.currentItem.width);
            // cc.log(x, centerNode.width, pageIdx)
        } else {
            // TODO: 纵向实现
        }
        EventManager.ins.emit(EVENT_NAME_ENUM.UPDATE_LEVEL_PAGE_LABEL, pageIdx + 1);
    }

    onTouchMove(touch: cc.Event.EventTouch) {
        this.content.x += touch.getDeltaX() * 1;
    }
    updatePage() {
        // 检测节点哪个距离中心点最近
        let minDistance = Number.MAX_VALUE;
        let closePos = null;
        let idx = 0;
        for (let i = 0; i < this.itemNodeList.length; ++i) {
            let posAtScrollView = Tools.getToNodePosForNode(this.itemNodeList[i], this.node);
            let distance = posAtScrollView.sub(this.node.getPosition()).mag()
            if (distance < minDistance) {
                idx = i;
                minDistance = distance;
                closePos = posAtScrollView;
            }
        }
        let offset = this.scrollView.getScrollOffset();

        if (this.scrollView.horizontal) {
            // cc.log("回弹前", -offset.x, pos.x)
            offset.x = -offset.x + closePos.x;
            // cc.log(Math.floor(offset.x), closePos.x);
        } else {
            // TODO: 纵向实现
        }

        this.scrollView.scrollToOffset(offset, 0.5)
        this.currentItem = this.itemNodeList[idx];
        this.updatePageLabel();
    }
    getCurrentPage() {
        return this.currentItem.getComponent(PageNode);
    }

    updateLockState() {
        for (let i = 0; i < this.itemNodeList.length; i++) {
            this.itemNodeList[i].getComponent(PageNode).updateLockState();
        }
    }
}